package com.cuiweiyou.uiautomator20;

import android.util.Log;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;

import jackmego.com.jieba_android.JiebaSegmenter;
import jackmego.com.jieba_android.SegToken;

/**
 * www.gaohaiyan.com
 */
public class ManagerGimmick {
    private static ManagerGimmick instance;

    private List<ModelCommGimmick> commGimmickList; // 话术文案
    private List<ModelHelloGimmick> helloGimmickList;

    private ManagerGimmick() {
    }

    public static ManagerGimmick getInstance() {
        if (null == instance) {
            synchronized (ManagerGimmick.class) {
                if (null == instance) {
                    instance = new ManagerGimmick();
                }
            }
        }
        return instance;
    }

    public void init() { // 加载话术文案
        initCommGimmicks();
        initHelloGimmicks();
    }

    private void initCommGimmicks() { // 加载话术文案
        commGimmickList = new ArrayList<>();

        File gimmickFile = UtilFile.getCommGimmickFile();
        if (!gimmickFile.exists()) {
            UtilLogs.saveLog("没有comm话术文件");
            return;
        }

        try {
            InputStream is = new FileInputStream(gimmickFile);
            BufferedReader reader = new BufferedReader(new InputStreamReader(is));
            String line;
            StringBuilder sb = new StringBuilder();
            while (null != (line = reader.readLine())) {
                line = line.trim();
                if (line.startsWith("===")) { // 新的一句
                    saveCommGimmick(sb);
                }
                sb.append(line + "$*$");
            }

            saveCommGimmick(sb);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void initHelloGimmicks() { // 加载话术文案
        helloGimmickList = new ArrayList<>();

        File gimmickFile = UtilFile.getHelloGimmickFile();
        if (!gimmickFile.exists()) {
            UtilLogs.saveLog("没有hello话术文件");
            return;
        }

        try {
            InputStream is = new FileInputStream(gimmickFile);
            BufferedReader reader = new BufferedReader(new InputStreamReader(is));
            String line;
            StringBuilder sb = new StringBuilder();
            while (null != (line = reader.readLine())) {
                line = line.trim();
                if (line.startsWith("===")) { // 新的一句
                    saveHelloGimmick(sb);
                }
                sb.append(line + "$*$");
            }

            saveHelloGimmick(sb);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void saveCommGimmick(StringBuilder sb) {
        if (sb.length() > 0) {
            String last3Char = sb.substring(sb.length() - 3, sb.length());
            if ("$*$".equals(last3Char)) {
                sb = sb.deleteCharAt(sb.length() - 1);
                sb = sb.deleteCharAt(sb.length() - 1);
                sb = sb.deleteCharAt(sb.length() - 1);
            }

            if (sb.length() > 0) {
                transformCommItem(sb.toString()); // 初始化话术
                sb.delete(0, sb.length());
            }
        }
    }

    private void saveHelloGimmick(StringBuilder sb) {
        if (sb.length() > 0) {
            String last3Char = sb.substring(sb.length() - 3, sb.length());
            if ("$*$".equals(last3Char)) {
                sb = sb.deleteCharAt(sb.length() - 1);
                sb = sb.deleteCharAt(sb.length() - 1);
                sb = sb.deleteCharAt(sb.length() - 1);
            }

            if (sb.length() > 0) {
                transformHelloItem(sb.toString()); // 初始化话术
                sb.delete(0, sb.length());
            }
        }
    }

    private void transformCommItem(String item) {
        String[] split = item.split("<<>>");

        UtilLogs.saveLog("comm话术读取行：" + item);
        UtilLogs.saveLog("comm话术行拆分：" + split.length);

        String index = split[0];
        index = index.replace("===", "");
        String side = "other";
        if (index.startsWith("M")) { // 回复，me
            side = "me";
            index = index.replaceFirst("M", "");
        } else if (index.startsWith("O")) { // 对方的话，other
            side = "other";
            index = index.replaceFirst("O", "");
        }

        String text = split[1];
        text = text.replace("$*$", System.getProperty("line.separator"));
        text = text.trim();

        String last = split[2];
        String next = split[3];

        ModelCommGimmick commGimmick = new ModelCommGimmick(side, index, text, last, next);
        commGimmickList.add(commGimmick);
    }

    private void transformHelloItem(String item) {
        String[] split = item.split("<<>>");

        UtilLogs.saveLog("hello话术读取行：" + item);
        UtilLogs.saveLog("hello话术行拆分：" + split.length);

        String index = split[0];
        index = index.replace("===", "");
        index = index.replaceFirst("A", "");

        String text = split[1];
        text = text.replace("$*$", System.getProperty("line.separator"));
        text = text.trim();

        ModelHelloGimmick helloGimmick = new ModelHelloGimmick(index, text);
        helloGimmickList.add(helloGimmick);
    }

    /**
     * 根据客户的语句，返回回复语句
     *
     * @param list
     * @return
     */
    public List<String> getAnswer(List<String> list) {
        ArrayList<String> otherMsgList = new ArrayList<>();
        otherMsgList.addAll(list);

        List<String> answerList = new ArrayList<>();

        UtilLogs.saveLog("对方的消息数量：" + otherMsgList.size());

        if (otherMsgList.size() > 0) {

            // 打招呼语句处理
            boolean hasAnsweredHello = false;
            for (int i = 0; i < list.size(); i++) {
                String omsg = list.get(i);

                UtilLogs.saveLog("对方消息处理：" + omsg);

                if (!"_+_".equals(omsg)) { // 对方的消息拿到了
                    boolean isHelloWord = ManagerWord.getInstance().isHelloWord(omsg);
                    if (isHelloWord) { // 是固定的打招呼句式
                        UtilLogs.saveLog("这是问好消息");
                        otherMsgList.remove(omsg);

                        if (!hasAnsweredHello) { // 已经有
                            int size = helloGimmickList.size();
                            int index = new Random().nextInt(size);
                            ModelHelloGimmick helloGimmick = helloGimmickList.get(index);

                            UtilLogs.saveLog("通过后打招呼回复：" + helloGimmick);

                            String answerMsg = helloGimmick.getGimmick();// 打招呼固定句式的回复
                            answerList.add(answerMsg);
                            hasAnsweredHello = true;
                        }
                    }
                }
            }

            if (otherMsgList.size() < 1) {
                UtilLogs.saveLog("没有更多消息了");
                return answerList;
            }

            // 有意义语句处理
            List<String> tmpAnswer = new ArrayList<>();
            for (int i = 0; i < otherMsgList.size(); i++) {
                String question = otherMsgList.get(i);
                UtilLogs.saveLog("消息：" + question);
                if (!"_+_".equals(question)) { // 对方的消息拿到了

                    ModelCommGimmick gimmickModel = getQuestionGimmickModel(question);// 直接匹配话术
                    if (null != gimmickModel) {
                        UtilLogs.saveLog("这是文案中完全匹配的问话");

                        // 1.为话术取一个回复
                        String index = getRandomAnswerGimmickIndex(gimmickModel);
                        UtilLogs.saveLog("取回复索引：" + index);

                        // 2.取回复
                        ModelCommGimmick gimmick = getGimmick(index); // 直接匹配到的话术取回复
                        String answer = gimmick.getGimmick();
                        UtilLogs.saveLog("回复：" + answer);

                        // 3.保存
                        if (!tmpAnswer.contains(answer)) {
                            tmpAnswer.add(answer);
                        }

                        continue;
                    }

                    // 1.去掉无意义词汇
                    String msg = ManagerWord.getInstance().delNormalOtherWord(question);
                    UtilLogs.saveLog("消息去除无意义词汇后：" + msg);

                    if (null == msg || msg.length() < 1) {
                        UtilLogs.saveLog("消息没有内容了");
                        continue;
                    }

                    // 2.提取固定词汇
                    List<String> fixedWord = ManagerWord.getInstance().getFixedWord(msg);
                    UtilLogs.saveLog("消息提取固定词汇：" + fixedWord.size());

                    // 3.结巴分词
                    List<SegToken> segList = JiebaSegmenter.getJiebaSegmenterSingleton().process(msg, JiebaSegmenter.SegMode.INDEX);
                    UtilLogs.saveLog("消息结巴分词：" + segList.size());

                    List<String> dividedList = new ArrayList<>();
                    for (int j = 0; j < segList.size(); j++) {
                        SegToken seg = segList.get(j);
                        dividedList.add(seg.word);
                    }

                    // 4.提取近义词
                    List<String> homoionymWord = new ArrayList<>();
                    for (int j = 0; j < dividedList.size(); j++) {
                        String word = dividedList.get(j);
                        List<String> hList = ManagerWord.getInstance().getHomoionymWord(word);
                        homoionymWord.addAll(hList);
                    }
                    UtilLogs.saveLog("消息近义词：" + homoionymWord.size());

                    // 5.匹配话术
                    List<String> keyWordList = new ArrayList<>();
                    for (int j = 0; j < fixedWord.size(); j++) {
                        String word = fixedWord.get(j);
                        if (!keyWordList.contains(word)) {
                            keyWordList.add(word);
                        }
                    }
                    for (int j = 0; j < dividedList.size(); j++) {
                        String word = dividedList.get(j);
                        if (!keyWordList.contains(word)) {
                            keyWordList.add(word);
                        }
                    }
                    for (int j = 0; j < homoionymWord.size(); j++) {
                        String word = homoionymWord.get(j);
                        if (!keyWordList.contains(word)) {
                            keyWordList.add(word);
                        }
                    }
                    UtilLogs.saveLog("消息最终分词：" + keyWordList.toString());

                    ModelCommGimmick model = getUnFixedSentences(keyWordList);
                    UtilLogs.saveLog("消息匹配：" + model);

                    // 6.为话术取一个回复
                    String index = getRandomAnswerGimmickIndex(model);
                    UtilLogs.saveLog("消息回复index：" + index);

                    // 7.取回复
                    String answer = "";
                    ModelCommGimmick gimmick = getGimmick(index); // 分词匹配后拿到的话术进行回复
                    if (null != gimmick) {
                        answer = gimmick.getGimmick();
                        UtilLogs.saveLog("消息回复内容1：" + answer);
                    }

                    // 8.保存
                    if (!"".equals(answer) && !tmpAnswer.contains(answer)) {
                        answer = ManagerWord.getInstance().getPrefixAnswerMsg() + answer;
                        UtilLogs.saveLog("消息回复内容2：" + answer);
                        tmpAnswer.add(answer);
                    }
                }
            }

            UtilLogs.saveLog("消息完整回复内容：" + tmpAnswer.size());
            answerList.addAll(tmpAnswer);

            if (answerList.size() < 1) { // 如果对方的多个消息都没有匹配到
                // 这里注释掉，表示"不理解的"就不回答
                //String emptyAnswer = ManagerWord.getInstance()
                //                                .getRandomEmptyAnswerMsg();// 返回一个随意聊天消息
                //System.out.println("随意聊天消息：" + emptyAnswer);
                //answerList.add(emptyAnswer);
                UtilLogs.saveLog("无匹配话术，临时不处理1");
            }

        } else { // 对方没有真人消息，为默认系统提示消息
            // 这里注释掉，表示"不理解的"就不回答
            //String answerMsg = ManagerWord.getInstance()
            //                              .getRandomEmptyAnswerMsg(); // 固定句式回复，对方消息为空
            //answerList.add(answerMsg);
            UtilLogs.saveLog("无真人消息，临时不处理2");
        }

        return answerList;
    }

    // 直接看看这句话是不是在话术文案里
    private ModelCommGimmick getQuestionGimmickModel(String string) {
        for (int j = 0; j < commGimmickList.size(); j++) {
            ModelCommGimmick bean = commGimmickList.get(j);
            String text = bean.getGimmick().trim();

            if ("other".equals(bean.getSide())) {
                if (string.equals(text)) {
                    UtilLogs.saveLog("匹配到了相同语句：" + bean);
                    return bean;
                }
            }
        }

        return null;
    }

    /**
     * 根据词汇匹配话术<br/>
     * 匹配到的词汇越多，越优先返回
     *
     * @param wordList 词汇集合
     * @return
     */
    private ModelCommGimmick getUnFixedSentences(List<String> wordList) {
        if (null == wordList || wordList.size() < 1) {
            return null;
        }

        Map<ModelCommGimmick, Integer> mateMap = new HashMap<>();       // 记录一句话术匹配到的词汇数量
        Map<String, List<ModelCommGimmick>> countMap = new HashMap<>(); // 按匹配数量记录话术
        for (int j = 0; j < commGimmickList.size(); j++) {
            ModelCommGimmick bean = commGimmickList.get(j);

            if ("other".equals(bean.getSide())) {
                String text = bean.getGimmick();
                UtilLogs.saveLog("对方话术：" + text);

                int segmenterCount = 0;
                for (int i = 0; i < wordList.size(); i++) {
                    String word = wordList.get(i);
                    if (text.equals(word) || text.contains(word) || word.contains(text)) {
                        segmenterCount++;
                        UtilLogs.saveLog("匹配到的分词：" + word);
                    }
                }

                UtilLogs.saveLog("匹配词汇量：" + segmenterCount + "，" + bean);

                // 这一句话术，匹配到了segmenterCount个分词
                if (segmenterCount > 0) {
                    mateMap.put(bean, segmenterCount);
                    UtilLogs.saveLog("匹配到了 " + segmenterCount + " 个分词");
                }

                List<ModelCommGimmick> beanList = countMap.get(segmenterCount + "");
                if (null == beanList) {
                    beanList = new ArrayList<>();
                    countMap.put(segmenterCount + "", beanList);
                }

                // 在 匹配到segmenterCount个分词 的这一组里存入此话术
                beanList.add(bean);
                UtilLogs.saveLog("存储话术：" + bean);
            }
        }

        int sizeCount = countMap.size(); // 匹配个数 的分组数量。map的key即匹配的个数
        int sizeMate = mateMap.size();   // 被匹配到的话术。1表示只有一条话术可用
        UtilLogs.saveLog("匹配个数 的分组数量：" + sizeCount);
        UtilLogs.saveLog("被匹配到的话术数量：" + sizeMate);

        if (1 == sizeCount && sizeMate > 0) { // 话术匹配的次数都是一样的，并且是多条话术
            String count = countMap.keySet().iterator().next();

            UtilLogs.saveLog("分词匹配次数一样：" + count);

            ModelCommGimmick[] keys = mateMap.keySet().toArray(new ModelCommGimmick[0]);
            ModelCommGimmick randomKey = keys[new Random().nextInt(keys.length)]; // 随机选一条适配

            UtilLogs.saveLog("随机选一条适配：" + randomKey);

            return randomKey;
        }

        // 如果匹配到了多条，且次数不一样
        if (!mateMap.isEmpty()) {
            Iterator<ModelCommGimmick> iterator = mateMap.keySet().iterator();
            ModelCommGimmick result = null;
            int count = 0;
            while (iterator.hasNext()) {
                ModelCommGimmick next = iterator.next();
                int integer = mateMap.get(next).intValue();
                if (integer > count) {
                    count = integer;
                    result = next;
                }
            }

            UtilLogs.saveLog("最接近对方话术的是：" + result);

            return result;
        }

        UtilLogs.saveLog("未匹配到的对方话术索引");
        return null;
    }

    // 为对方的非固定句式消息匹配一个回复，返回回复话术的索引
    private String getRandomAnswerGimmickIndex(ModelCommGimmick gimmick) {
        if (null == gimmick) {
            UtilLogs.saveLog("没有话术");
            return null;
        }

        String nexts = gimmick.getNext();
        String[] split = nexts.split(",");
        int i1 = new Random().nextInt(split.length); // 回答话术的索引
        String index = split[i1];

        UtilLogs.saveLog("挑选一个回复话术的索引：" + index);

        if ("-1".equals(index)) {
            UtilLogs.saveLog("话术的索引 null");
            return null;
        }

        return index;
    }

    // 根据索引提取一个话术
    private ModelCommGimmick getGimmick(String answerIndex) {
        if (null == answerIndex) {
            return null;
        }

        for (int k = 0; k < commGimmickList.size(); k++) {
            ModelCommGimmick sb = commGimmickList.get(k);
            String index = sb.getIndex();
            if (index.equals(answerIndex)) {
                UtilLogs.saveLog("根据索引提取一个话术：" + sb);
                return sb;
            }
        }

        UtilLogs.saveLog("未能根据索引提取一个话术");

        return null;
    }

}
